package com.eshop.modules.order.rest;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.slf4j.LoggerFactory;
import java.lang.invoke.SerializedLambda;
import java.math.BigDecimal;
import java.util.Map;
import java.text.ParseException;
import java.io.IOException;
import com.alibaba.fastjson.JSONArray;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletResponse;
import com.eshop.tools.express.dao.ExpressInfo;
import com.eshop.tools.express.ExpressService;
import com.eshop.tools.express.config.ExpressAutoConfiguration;
import com.eshop.enums.ShipperCodeEnum;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import org.springframework.web.bind.annotation.DeleteMapping;
import com.eshop.logging.aop.log.Log;
import com.eshop.modules.aop.ForbidSubmit;
import org.springframework.web.bind.annotation.PostMapping;
import com.eshop.enums.ShopCommonEnum;
import com.eshop.enums.OrderInfoEnum;
import java.io.Serializable;
import com.eshop.modules.order.service.dto.StoreOrderDto;
import org.springframework.web.bind.annotation.PutMapping;
import com.eshop.exception.BadRequestException;
import cn.hutool.core.util.StrUtil;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.validation.annotation.Validated;
import com.eshop.modules.order.domain.StoreOrder;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import com.eshop.modules.order.service.dto.StoreOrderStatusDto;
import java.util.List;
import com.eshop.modules.order.service.dto.OrderNowOrderStatusDto;
import java.util.Collection;
import com.eshop.modules.order.domain.StoreOrderStatus;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.eshop.enums.OrderLogEnum;
import java.util.ArrayList;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.data.domain.Pageable;
import com.eshop.modules.order.service.dto.StoreOrderQueryCriteria;
import com.eshop.annotation.AnonymousAccess;
import com.eshop.modules.order.param.ExpressParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import com.eshop.modules.order.service.dto.OrderCountDto;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import com.eshop.modules.order.service.StoreOrderStatusService;
import com.eshop.modules.order.service.StoreOrderService;
import com.eshop.dozer.service.IGenerator;
import org.slf4j.Logger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;

@Api(tags = { "商城:订单管理" })
@RestController
@RequestMapping({ "api" })
public class StoreOrderController
{
    private static final Logger log;
    private final IGenerator generator;
    private final StoreOrderService storeOrderService;
    private final StoreOrderStatusService storeOrderStatusService;
    
    public StoreOrderController(final IGenerator generator, final StoreOrderService storeOrderService, final StoreOrderStatusService storeOrderStatusService) {
        this.generator = generator;
        this.storeOrderService = storeOrderService;
        this.storeOrderStatusService = storeOrderStatusService;
    }
    
    @GetMapping({ "/yxStoreOrder/orderCount" })
    @ApiOperation(value = "根据商品分类统计订单占比", notes = "根据商品分类统计订单占比", response = ExpressParam.class)
    public ResponseEntity orderCount() {
        final OrderCountDto orderCountDto = this.storeOrderService.getOrderCount();
        return new ResponseEntity(orderCountDto, HttpStatus.OK);
    }
    
    @GetMapping({ "/data/count" })
    @AnonymousAccess
    public ResponseEntity getCount() {
        return new ResponseEntity(this.storeOrderService.getOrderTimeData(), HttpStatus.OK);
    }
    
    @GetMapping({ "/data/chart" })
    @AnonymousAccess
    public ResponseEntity getChart() {
        return new ResponseEntity(this.storeOrderService.chartCount(), HttpStatus.OK);
    }
    
    @ApiOperation("查询订单")
    @GetMapping({ "/yxStoreOrder" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREORDER_ALL','YXSTOREORDER_SELECT','YXEXPRESS_SELECT')")
    public ResponseEntity getYxStoreOrders(final StoreOrderQueryCriteria criteria, final Pageable pageable, @RequestParam(name = "orderStatus") final String orderStatus, @RequestParam(name = "orderType") final String orderType) {
        final StoreOrderQueryCriteria newCriteria = this.handleQuery(criteria, orderStatus, orderType);
        return new ResponseEntity(this.storeOrderService.queryAll(newCriteria, pageable), HttpStatus.OK);
    }
    
    @ApiOperation("根据订单id获取订单详情")
    @GetMapping({ "/getStoreOrderDetail/{id}" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREORDER_ALL','YXSTOREORDER_SELECT','YXEXPRESS_SELECT')")
    public ResponseEntity getYxStoreOrders(@PathVariable final Long id) {
        return new ResponseEntity(this.storeOrderService.getOrderDetail(id), HttpStatus.OK);
    }
    
    @ApiOperation("查询订单当前状态流程")
    @GetMapping({ "/getNowOrderStatus/{id}" })
    public ResponseEntity getNowOrderStatus(@PathVariable final Long id) {
        List<String> statusList = new ArrayList<String>();
        statusList.add(OrderLogEnum.CREATE_ORDER.getValue());
        statusList.add(OrderLogEnum.PAY_ORDER_SUCCESS.getValue());
        statusList.add(OrderLogEnum.DELIVERY_GOODS.getValue());
        statusList.add(OrderLogEnum.TAKE_ORDER_DELIVERY.getValue());
        statusList.add(OrderLogEnum.EVAL_ORDER.getValue());
        List<StoreOrderStatus> orderStatusLogList = (List<StoreOrderStatus>)this.storeOrderStatusService.list(((Wrappers.<StoreOrderStatus>lambdaQuery().eq(StoreOrderStatus::getOid, id)).in(StoreOrderStatus::getChangeType, (Collection)statusList)).orderByDesc(StoreOrderStatus::getChangeTime));
        List<StoreOrderStatusDto> dtoList = this.getOrderStatusDto(orderStatusLogList);
        final OrderNowOrderStatusDto orderNowOrderStatusDto = new OrderNowOrderStatusDto();
        orderNowOrderStatusDto.setSize(dtoList.size());
        dtoList.forEach(dto -> {
            if (OrderLogEnum.CREATE_ORDER.getDesc().equals(dto.getChangeType())) {
                orderNowOrderStatusDto.setCacheKeyCreateOrder(dto.getChangeTime());
            }
            if (OrderLogEnum.PAY_ORDER_SUCCESS.getDesc().equals(dto.getChangeType())) {
                orderNowOrderStatusDto.setPaySuccess(dto.getChangeTime());
            }
            if (OrderLogEnum.DELIVERY_GOODS.getDesc().equals(dto.getChangeType())) {
                orderNowOrderStatusDto.setDeliveryGoods(dto.getChangeTime());
            }
            if (OrderLogEnum.TAKE_ORDER_DELIVERY.getDesc().equals(dto.getChangeType())) {
                orderNowOrderStatusDto.setUserTakeDelivery(dto.getChangeTime());
                orderNowOrderStatusDto.setOrderVerific(dto.getChangeTime());
            }
            if (OrderLogEnum.EVAL_ORDER.getDesc().equals(dto.getChangeType())) {
                orderNowOrderStatusDto.setCheckOrderOver(dto.getChangeTime());
            }
            return;
        });
        statusList = new ArrayList<String>();
        statusList.add(OrderLogEnum.REFUND_ORDER_APPLY.getValue());
        statusList.add(OrderLogEnum.REFUND_ORDER_SUCCESS.getValue());
        orderStatusLogList = (List<StoreOrderStatus>)this.storeOrderStatusService.list(((Wrappers.<StoreOrderStatus>lambdaQuery().eq(StoreOrderStatus::getOid, id)).in(StoreOrderStatus::getChangeType, (Collection)statusList)).orderByDesc(StoreOrderStatus::getChangeTime));
        dtoList = this.getOrderStatusDto(orderStatusLogList);
        dtoList.forEach(dto -> {
            if (OrderLogEnum.REFUND_ORDER_APPLY.getDesc().equals(dto.getChangeType())) {
                orderNowOrderStatusDto.setApplyRefund(dto.getChangeTime());
            }
            if (OrderLogEnum.REFUND_ORDER_SUCCESS.getDesc().equals(dto.getChangeType())) {
                orderNowOrderStatusDto.setRefundOrderSuccess(dto.getChangeTime());
            }
            return;
        });
        return new ResponseEntity(orderNowOrderStatusDto, HttpStatus.OK);
    }
    
    public List<StoreOrderStatusDto> getOrderStatusDto(final List<StoreOrderStatus> orderStatusLogList) {
        final List<StoreOrderStatusDto> dtoList = orderStatusLogList.stream().map(log -> {
            StoreOrderStatusDto dto = (StoreOrderStatusDto)this.generator.convert(log, (Class)StoreOrderStatusDto.class);
            dto.setChangeType(OrderLogEnum.getDesc(dto.getChangeType()));
            dto.setChangeTime(log.getChangeTime());
            return dto;
        }).collect(Collectors.toList());
        return dtoList;
    }
    
    @ApiOperation("发货")
    @PutMapping({ "/yxStoreOrder" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREORDER_ALL','YXSTOREORDER_EDIT')")
    public ResponseEntity update(@Validated @RequestBody final StoreOrder resources) {
        if (StrUtil.isBlank((CharSequence)resources.getDeliveryName())) {
            throw new BadRequestException("请选择快递公司");
        }
        if (StrUtil.isBlank((CharSequence)resources.getDeliveryId())) {
            throw new BadRequestException("快递单号不能为空");
        }
        this.storeOrderService.orderDelivery(resources.getOrderId(), resources.getDeliveryId(), resources.getDeliveryName(), resources.getDeliveryType());
        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }
    
    @ApiOperation("修改快递单号")
    @PutMapping({ "/yxStoreOrder/updateDelivery" })
    @PreAuthorize("hasAnyAuthority('admin','YXSTOREORDER_ALL','YXSTOREORDER_EDIT')")
    public ResponseEntity updateDelivery(@Validated @RequestBody final StoreOrder resources) {
        if (StrUtil.isBlank((CharSequence)resources.getDeliveryName())) {
            throw new BadRequestException("请选择快递公司");
        }
        if (StrUtil.isBlank((CharSequence)resources.getDeliveryId())) {
            throw new BadRequestException("快递单号不能为空");
        }
        this.storeOrderService.updateDelivery(resources.getOrderId(), resources.getDeliveryId(), resources.getDeliveryName(), resources.getDeliveryType());
        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }
    
    @ApiOperation("订单核销")
    @PutMapping({ "/yxStoreOrder/check" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREORDER_ALL','YXSTOREORDER_EDIT')")
    public ResponseEntity check(@Validated @RequestBody final StoreOrder resources) {
        if (StrUtil.isBlank((CharSequence)resources.getVerifyCode())) {
            throw new BadRequestException("核销码不能为空");
        }
        final StoreOrderDto storeOrderDTO = (StoreOrderDto)this.generator.convert(this.storeOrderService.getById((Serializable)resources.getId()), (Class)StoreOrderDto.class);
        if (!resources.getVerifyCode().equals(storeOrderDTO.getVerifyCode())) {
            throw new BadRequestException("核销码不对");
        }
        if (OrderInfoEnum.PAY_STATUS_0.getValue().equals(storeOrderDTO.getPaid())) {
            throw new BadRequestException("订单未支付");
        }
        this.storeOrderService.verifyOrder(resources.getVerifyCode(), OrderInfoEnum.CONFIRM_STATUS_1.getValue(), (Long)null);
        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }
    
    @ApiOperation("退款")
    @PostMapping({ "/yxStoreOrder/refund" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREORDER_ALL','YXSTOREORDER_EDIT')")
    public ResponseEntity refund(@Validated @RequestBody final StoreOrder resources) {
        this.storeOrderService.orderRefund(resources.getOrderId(), resources.getPayPrice(), ShopCommonEnum.AGREE_1.getValue());
        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }
    
    @ForbidSubmit
    @Log("删除")
    @ApiOperation("删除")
    @DeleteMapping({ "/yxStoreOrder/{id}" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREORDER_ALL','YXSTOREORDER_DELETE')")
    public ResponseEntity delete(@PathVariable final Integer id) {
        this.storeOrderService.removeById((Serializable)id);
        return new ResponseEntity(HttpStatus.OK);
    }
    
    @Log("修改订单")
    @ApiOperation("修改订单")
    @PostMapping({ "/yxStoreOrder/edit" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREORDER_ALL','YXSTOREORDER_EDIT')")
    public ResponseEntity editOrder(@RequestBody final StoreOrder resources) {
        if (ObjectUtil.isNull(resources.getPayPrice())) {
            throw new BadRequestException("请输入支付金额");
        }
        if (resources.getPayPrice().doubleValue() < 0.0) {
            throw new BadRequestException("金额不能低于0");
        }
        final StoreOrderDto storeOrder = (StoreOrderDto)this.generator.convert(this.storeOrderService.getById((Serializable)resources.getId()), (Class)StoreOrderDto.class);
        final int res = NumberUtil.compare(storeOrder.getPayPrice().doubleValue(), resources.getPayPrice().doubleValue());
        if (res != 0) {
            final String orderSn = IdUtil.getSnowflake(0L, 0L).nextIdStr();
            resources.setExtendOrderId(orderSn);
        }
        this.storeOrderService.saveOrUpdate(resources);
        this.storeOrderStatusService.create(resources.getId(), OrderLogEnum.ORDER_EDIT.getValue(), "修改订单价格为：" + resources.getPayPrice());
        return new ResponseEntity(HttpStatus.OK);
    }
    
    @Log("修改订单备注")
    @ApiOperation("修改订单备注")
    @PostMapping({ "/yxStoreOrder/remark" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREORDER_ALL','YXSTOREORDER_EDIT')")
    public ResponseEntity editOrderRemark(@RequestBody final StoreOrder resources) {
        if (StrUtil.isBlank((CharSequence)resources.getRemark())) {
            throw new BadRequestException("请输入备注");
        }
        this.storeOrderService.saveOrUpdate(resources);
        return new ResponseEntity(HttpStatus.OK);
    }
    
    @PostMapping({ "/yxStoreOrder/express" })
    @ApiOperation(value = "获取物流信息", notes = "获取物流信息", response = ExpressParam.class)
    public ResponseEntity express(@RequestBody final ExpressParam expressInfoDo) {
        String lastFourNumber = "";
        if (expressInfoDo.getShipperCode().equals(ShipperCodeEnum.SF.getValue())) {
            final StoreOrderDto storeOrderDto = this.storeOrderService.getOrderDetail(Long.valueOf(expressInfoDo.getOrderCode()));
            lastFourNumber = storeOrderDto.getUserPhone();
            if (lastFourNumber.length() == 11) {
                lastFourNumber = StrUtil.sub((CharSequence)lastFourNumber, lastFourNumber.length(), -4);
            }
        }
        final ExpressService expressService = ExpressAutoConfiguration.expressService();
        final ExpressInfo expressInfo = expressService.getExpressInfo(expressInfoDo.getOrderCode(), expressInfoDo.getShipperCode(), expressInfoDo.getLogisticCode(), lastFourNumber);
        if (!expressInfo.isSuccess()) {
            throw new BadRequestException(expressInfo.getReason());
        }
        return new ResponseEntity(expressInfo, HttpStatus.OK);
    }
    
    @Log("导出数据")
    @ApiOperation("导出数据")
    @GetMapping({ "/yxStoreOrder/download" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREORDER_SELECT')")
    public void download(final HttpServletResponse response, final StoreOrderQueryCriteria criteria, final Pageable pageable, @RequestParam(name = "orderStatus") final String orderStatus, @RequestParam(name = "orderType") final String orderType, @RequestParam(name = "listContent") final String listContent) throws IOException, ParseException {
        List<StoreOrderDto> list;
        if (StringUtils.isEmpty((CharSequence)listContent)) {
            list = (List<StoreOrderDto>) this.getYxStoreList(criteria, pageable, orderStatus, orderType).get("content");
        }
        else {
            final List<String> idList = (List<String>)JSONArray.parseArray(listContent).toJavaList((Class)String.class);
            list = (List<StoreOrderDto>) this.storeOrderService.queryAll((List)idList).get("content");
        }
        this.storeOrderService.download((List)list, response);
    }
    
    private Map<String, Object> getYxStoreList(final StoreOrderQueryCriteria criteria, final Pageable pageable, final String orderStatus, final String orderType) {
        final StoreOrderQueryCriteria newCriteria = this.handleQuery(criteria, orderStatus, orderType);
        return (Map<String, Object>)this.storeOrderService.queryAll(newCriteria, pageable);
    }
    
    private StoreOrderQueryCriteria handleQuery(final StoreOrderQueryCriteria criteria, final String orderStatus, final String orderType) {
        criteria.setShippingType(OrderInfoEnum.SHIPPIING_TYPE_1.getValue());
        if (StrUtil.isNotEmpty((CharSequence)orderStatus)) {
            switch (orderStatus) {
                case "0": {
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_0.getValue());
                    criteria.setStatus(OrderInfoEnum.STATUS_0.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_0.getValue());
                    break;
                }
                case "1": {
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setStatus(OrderInfoEnum.STATUS_0.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_0.getValue());
                    break;
                }
                case "2": {
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setStatus(OrderInfoEnum.STATUS_1.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_0.getValue());
                    break;
                }
                case "3": {
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setStatus(OrderInfoEnum.STATUS_2.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_0.getValue());
                    break;
                }
                case "4": {
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setStatus(OrderInfoEnum.STATUS_3.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_0.getValue());
                    break;
                }
                case "-1": {
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_1.getValue());
                    break;
                }
                case "-2": {
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_2.getValue());
                    break;
                }
            }
        }
        if (StrUtil.isNotEmpty((CharSequence)orderType)) {
            switch (orderType) {
                case "1": {
                    criteria.setBargainId(Integer.valueOf(0));
                    criteria.setCombinationId(Integer.valueOf(0));
                    criteria.setSeckillId(Integer.valueOf(0));
                    break;
                }
                case "2": {
                    criteria.setNewCombinationId(Integer.valueOf(0));
                    break;
                }
                case "3": {
                    criteria.setNewSeckillId(Integer.valueOf(0));
                    break;
                }
                case "4": {
                    criteria.setNewBargainId(Integer.valueOf(0));
                    break;
                }
                case "5": {
                    criteria.setShippingType(Integer.valueOf(2));
                    break;
                }
                case "6": {
                    criteria.setPayIntegral(new BigDecimal("0.00"));
                    break;
                }
            }
        }
        return criteria;
    }
    
    static {
        log = LoggerFactory.getLogger((Class)StoreOrderController.class);
    }
}
